home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus Leser 15 / Amiga Plus Leser CD 15.iso / Tools / Development / mmu / MuManual / C_Sources / MuFastRom.c < prev    next >
C/C++ Source or Header  |  2002-03-12  |  22KB  |  563 lines

  1. /*****************************************************************
  2.  ** MuFastRom                                                   **
  3.  **                                                             **
  4.  ** A MMU-Library compatible ROM remapper                       **
  5.  ** Version 40.9 24.12.2001 © THOR-Software, by Thomas Richter  **
  6.  *****************************************************************/
  7.  
  8. /// Includes
  9. #include <exec/types.h>
  10. #include <exec/memory.h>
  11. #include <exec/ports.h>
  12. #include <dos/dos.h>
  13. #include <mmu/mmubase.h>
  14. #include <mmu/context.h>
  15. #include <mmu/mmutags.h>
  16. #include <workbench/startup.h>
  17.  
  18. #include <proto/exec.h>
  19. #include <proto/mmu.h>
  20. #include <proto/dos.h>
  21. #include <proto/icon.h>
  22. #include <string.h>
  23. ///
  24. /// Defines
  25. #define STRINGDATE "24.7.2001"
  26. #define STRINGVERSION "40.9"
  27. #define ROMEND 0x01000000L
  28. #define MAGIC_ROMEND 0x14L
  29. #define CACHEFLAGS (MAPP_CACHEINHIBIT|MAPP_COPYBACK|MAPP_NONSERIALIZED|MAPP_IMPRECISE)
  30. #define TEMPLATE "ON=FASTROM/S,OFF=NOFASTROM/S,HEAD/S,PROTECT/S,NOPROTECT/S"
  31.  
  32. #define OPT_ON  0
  33. #define OPT_OFF 1
  34. #define OPT_HEAD 2
  35. #define OPT_PROTECT 3
  36. #define OPT_NOPROTECT 4
  37. #define OPT_WINDOW 5
  38. #define OPT_COUNT 6
  39. ///
  40. /// Statics
  41. struct MMUBase *MMUBase;
  42. struct DosLibrary *DOSBase;
  43. struct ExecBase *SysBase;
  44. struct Library *IconBase;
  45. ///
  46. /// Protos
  47. int __asm __saveds main(void);
  48. int BuildFastRom(LONG head,LONG protect,LONG noprotect);
  49. int RemoveFastRom(void);
  50. BOOL MapToRom(struct MMUContext *ctx,ULONG oldlocation,ULONG source,ULONG mem,ULONG size);
  51. BOOL RemapToRam(struct MMUContext *ctx,ULONG source,ULONG pmem,ULONG mem,ULONG size,LONG protect,LONG noprotect,ULONG cacheflags);
  52. struct RDArgs *ReadTTArgs(struct WBStartup *msg,LONG args[],struct RDArgs **tmp);
  53. ///
  54. /// Strukturen
  55. struct FastRomPort {
  56.         struct MsgPort          frp_Port;
  57.         UBYTE                   frp_NoProtect;
  58.         UBYTE                   frp_Protect;
  59.         void                   *frp_Logical;            /* Logical address of the remapped ROM */
  60.         void                   *frp_Physical;           /* Physical location of the RAM used for remapping */
  61.         void                   *frp_RomStart;
  62.         ULONG                   frp_Size;               /* size of the allocated memory */
  63.         struct Library         *frp_Base;               /* Keep the library open */
  64.         ULONG                   frp_CacheFlags;         /* keeps the cache mode of the remapped ROM */
  65.         void                   *frp_OldLocation;        /* In case the ROM was remapped before, it was here. */
  66.         char                    frp_Name[32];           /* keeps the name of the port */
  67. };
  68. ///
  69.  
  70. char version[]="$VER: MuFastRom " STRINGVERSION " (" STRINGDATE ") © THOR";
  71.  
  72. /// main
  73. int __asm __saveds main(void)
  74. {
  75. LONG args[OPT_COUNT];
  76. struct RDArgs *rd,*myrd;
  77. struct Process *proc;
  78. int rc=20;
  79. LONG err;
  80. struct WBStartup *msg;
  81. BPTR oldout;
  82. struct MsgPort *oldconsole;
  83.  
  84.  
  85.  
  86.         SysBase=*((struct ExecBase **)(4L));
  87.  
  88.         memset(args,0,sizeof(LONG)*OPT_COUNT);
  89.         /* Wait for the workbench startup, if any */
  90.         proc=(struct Process *)FindTask(NULL);
  91.  
  92.         if (!(proc->pr_CLI)) {
  93.                 WaitPort(&(proc->pr_MsgPort));
  94.                 msg=(struct WBStartup *)GetMsg(&(proc->pr_MsgPort));
  95.         } else  msg=NULL;
  96.  
  97.         if (DOSBase=(struct DosLibrary *)OpenLibrary("dos.library",37L)) {
  98.                 if (MMUBase=(struct MMUBase *)OpenLibrary("mmu.library",41L)) {
  99.  
  100.                         err=ERROR_REQUIRED_ARG_MISSING;
  101.  
  102.                         myrd=NULL;      /* reset the temporary ReadArgs */
  103.                         oldout=NULL;
  104.                         oldconsole=NULL;
  105.                         if (msg) {
  106.                                 oldout=SelectOutput(NULL);
  107.                                 oldconsole=SetConsoleTask(NULL);
  108.                                 rd=ReadTTArgs(msg,args,&myrd);
  109.                         } else  rd=ReadArgs(TEMPLATE,args,NULL);
  110.  
  111.                         if (rd) {
  112.                                 if (!GetMMUType()) {
  113.                                         Printf("MuFastRom requires a working MMU.\n");
  114.                                         err=10;
  115.                                 } else {
  116.                                         /* Argument parser worked, call main routine */
  117.                                         if ((args[OPT_ON]) || (!args[OPT_OFF])) /* ON is the default if OFF is not given */
  118.                                                 err=BuildFastRom(args[OPT_HEAD],args[OPT_PROTECT],args[OPT_NOPROTECT]);
  119.  
  120.                                         if (args[OPT_OFF])
  121.                                                 err=RemoveFastRom();
  122.                                 }
  123.  
  124.                                 FreeArgs(rd);
  125.                                 if (myrd) FreeDosObject(DOS_RDARGS,myrd);
  126.                                 if (msg)  Close(SelectOutput(NULL));
  127.                         } else  err=IoErr();
  128.  
  129.                         if (msg) {
  130.                                 SelectOutput(oldout);
  131.                                 SetConsoleTask(oldconsole);
  132.                         }
  133.  
  134.                         if (err<64) {
  135.                                 rc=err;
  136.                                 err=0;
  137.                         } else {
  138.                                 if (!msg) PrintFault(err,"MuFastRom failed");
  139.                                 rc=10;
  140.                         }
  141.                         SetIoErr(err);
  142.  
  143.                         CloseLibrary((struct Library *)MMUBase);
  144.                 } else if (!msg) PrintFault(ERROR_OBJECT_NOT_FOUND,"MuFastRom requires the mmu.library V41 or better");
  145.                 CloseLibrary((struct Library *)DOSBase);
  146.         }
  147.  
  148.         if (msg) {
  149.                 Forbid();
  150.                 ReplyMsg((struct Message *)msg);
  151.         }
  152.  
  153.         return rc;
  154. }
  155. ///
  156. /// ReadTTArgs
  157. struct RDArgs *ReadTTArgs(struct WBStartup *msg,LONG args[],struct RDArgs **tmp)
  158. {
  159. struct WBArg *wbarg;
  160. struct DiskObject *dop;
  161. char **tt;                      /* ToolTypes array */
  162. char *wbstr;                    /* Our self-made workbench argument string */
  163. char *here;
  164. BPTR oldlock;
  165. ULONG len;
  166. struct RDArgs *rd=NULL,*myrd=NULL;
  167. LONG err=0;
  168. BPTR newout;
  169.  
  170.         if (IconBase=OpenLibrary("icon.library",37L)) {
  171.                 if (wbarg=msg->sm_ArgList) {
  172.                         /* use a project icon if there is one... */
  173.                         if (msg->sm_NumArgs > 1) wbarg++;
  174.  
  175.                         /* go into the directory */
  176.                         oldlock=CurrentDir(wbarg->wa_Lock);
  177.  
  178.                         if (dop=GetDiskObject(wbarg->wa_Name)) {
  179.                                 if (tt=dop->do_ToolTypes) {
  180.                                         /* Read a special tool type for the output window */
  181.  
  182.                                         /* Calc the size of the argument string */
  183.  
  184.                                         len = 3;        /* reserve space for SPC,LF,NUL */
  185.                                         while (*tt) {
  186.                                                 len += strlen(*tt)+1;   /* string, plus space */
  187.                                                 tt++;
  188.                                         }
  189.  
  190.                                         if (wbstr=AllocVec(len,MEMF_PUBLIC)) {
  191.                                                 /* Now copy the arguments into this string, one by one
  192.                                                    and check whether the argument string is still valid. */
  193.  
  194.                                                 tt=dop->do_ToolTypes;
  195.                                                 here=wbstr;
  196.                                                 do{
  197.                                                         *here='\0';                     /* terminate string */
  198.                                                         /* Check whether this tool type is
  199.                                                            commented out. Just ignore it in this case */
  200.                                                         if (*tt) {
  201.                                                                 if (**tt=='(' || **tt==';')
  202.                                                                         continue;
  203.  
  204.                                                                 strcpy(here,*tt);      /* Add TT string */
  205.                                                         }
  206.                                                         len=strlen(here);
  207.                                                         here[len]='\n';
  208.                                                         here[len+1]='\0';               /* terminate string */
  209.  
  210.                                                         /* Now try to ReadArg' this string */
  211.  
  212.                                                         /* release old arguments left over from last loop */
  213.                                                         if (rd) FreeArgs(rd);
  214.                                                         if (myrd) FreeDosObject(DOS_RDARGS,myrd);
  215.                                                         rd=NULL;
  216.                                                         memset(args,0,sizeof(LONG)*OPT_COUNT);
  217.  
  218.                                                         if (myrd=AllocDosObject(DOS_RDARGS,NULL)) {
  219.                                                                 /* Allocate and setup the ReadArgs source */
  220.                                                                 myrd->RDA_Source.CS_Buffer=wbstr;
  221.                                                                 myrd->RDA_Source.CS_Length=strlen(wbstr);
  222.  
  223.                                                                 if (rd=ReadArgs(TEMPLATE ",WINDOW/K",args,myrd)) {
  224.                                                                         /* Is this still valid? */
  225.                                                                         here[len]=' ';
  226.                                                                         here+=len+1;
  227.                                                                         /* if so, accept this argument and go on */
  228.                                                                 } else {
  229.                                                                         err=IoErr();
  230.                                                                         if (err==ERROR_NO_FREE_STORE) break;
  231.                                                                         else    err=0;  /* Ignore unknown or invalid arguments silently */
  232.                                                                 }
  233.                                                         } else {
  234.                                                                 err=ERROR_NO_FREE_STORE;
  235.                                                                 break;
  236.                                                         }
  237.                                                 }while(*tt++);
  238.  
  239.                                                 FreeVec(wbstr);
  240.                                         } else err=ERROR_NO_FREE_STORE;
  241.                                 } else err=ERROR_REQUIRED_ARG_MISSING; /* Huh, how should this happen ? */
  242.                                 FreeDiskObject(dop);
  243.                         } else err=IoErr();
  244.                         CurrentDir(oldlock);
  245.                 } else err=ERROR_REQUIRED_ARG_MISSING; /* This should not happen either */
  246.                 CloseLibrary(IconBase);
  247.         } else err=ERROR_OBJECT_NOT_FOUND;    /* This should not happen */
  248.  
  249.         /* Open an output stream */
  250.  
  251.         if (err==0) {
  252.                 if (newout=Open((args[OPT_WINDOW])?((char *)args[OPT_WINDOW]):("NIL:"),MODE_NEWFILE)) {
  253.                         SelectOutput(newout);
  254.                         /* Hack in the output console. Well, well... */
  255.                         SetConsoleTask(((struct FileHandle *)(BADDR(newout)))->fh_Type);
  256.                 } else err=IoErr();
  257.         }
  258.  
  259.         if (err) {
  260.                 if (rd)   FreeArgs(rd);
  261.                 if (myrd) FreeDosObject(DOS_RDARGS,myrd);
  262.                 SetIoErr(err);
  263.                 rd=NULL;
  264.                 myrd=NULL;
  265.         }
  266.  
  267.         *tmp=myrd;
  268.         return rd;
  269. }
  270. ///
  271. /// BuildFastRom
  272. int BuildFastRom(LONG head,LONG protect,LONG noprotect)
  273. {
  274. void *mem,*source,*pmem,*oldlocation;
  275. ULONG size,psize;
  276. ULONG props;
  277. struct FastRomPort *port;
  278. struct MMUContext *ctx,*sctx;   /* default context, supervisorcontext */
  279. struct MinList *ctxl,*sctxl;
  280. int err=ERROR_NO_FREE_STORE;
  281.  
  282.  
  283.         Forbid();                               /* Shut up PatchWork */
  284.  
  285.         /* If this is already installed, warn and return. */
  286.  
  287.         if (FindPort("« MuFastRom »")) {
  288.                 Permit();
  289.                 Printf("MuFastRom already running.\n");
  290.                 return 5;
  291.         }
  292.  
  293.         Permit();
  294.  
  295.         ctx=DefaultContext();   /* get the default context */
  296.         sctx=SuperContext(ctx); /* get the supervisor context for this one */
  297.  
  298.         /* Read the size of the ROM */
  299.         size=*((ULONG *)(ROMEND-MAGIC_ROMEND));
  300.  
  301.         /* The start of the ROM */
  302.         source=((UBYTE *)ROMEND)-size;
  303.  
  304.         props       = GetProperties(sctx,(ULONG)source,TAG_DONE);
  305.         props      |= GetProperties(ctx,(ULONG)source,TAG_DONE);
  306.         oldlocation = source;
  307.  
  308.         if (props & MAPP_REMAPPED) {
  309.                 ULONG romsize = size;
  310.                 /*
  311.                  * Find out where the ROM is going to
  312.                  */
  313.                 PhysicalLocation(ctx,&oldlocation,&romsize);
  314.                 if (romsize > 0 && (TypeOfMem(oldlocation) & MEMF_FAST)) {
  315.                         Printf("The ROM is already remapped to Fast RAM.\n");
  316.                         return 5;
  317.                 }
  318.         }
  319.  
  320.  
  321.         /* now allocate the memory for the ROM image. To keep the
  322.            MMU tables as effective as possible, we try to align
  323.            this */
  324.  
  325.         /* We request FAST here, explicitly. Taking chip memory for the
  326.            ROM image doesn't make sense, this isn't fast either... */
  327.  
  328.         mem=AllocAligned(size,(head)?(MEMF_PUBLIC|MEMF_FAST):(MEMF_REVERSE|MEMF_PUBLIC|MEMF_FAST),RemapSize(ctx));
  329.         if (mem) {
  330.  
  331.                 pmem=mem;
  332.                 psize=size;
  333.                 PhysicalLocation(ctx,&pmem,&psize);
  334.                 if (psize!=size) {
  335.                         Printf("The destination memory is fragmentated, unsupported.\n");
  336.                 } else {
  337.  
  338.                  /* Read the cache flags */
  339.                  props=GetProperties(ctx,(ULONG)mem,TAG_DONE) & CACHEFLAGS;
  340.  
  341.                  /* Copy the ROM */
  342.                  CopyMemQuick(source,mem,size);
  343.  
  344.                  /* Write it out, really */
  345.                  CacheClearU();
  346.  
  347.                  port=AllocMem(sizeof(struct FastRomPort),MEMF_PUBLIC|MEMF_CLEAR);
  348.                  if (port) {
  349.                         LockContextList();
  350.                         LockMMUContext(ctx);
  351.                         LockMMUContext(sctx);
  352.                         if (ctxl=GetMapping(ctx)) {
  353.                          if (sctxl=GetMapping(ctx)) {
  354.                           if (RemapToRam(ctx,(ULONG)source,(ULONG)pmem,(ULONG)mem,size,protect,noprotect,props)) {
  355.                            if (RemapToRam(sctx,(ULONG)source,(ULONG)pmem,(ULONG)mem,size,protect,noprotect,props)) {
  356.                             if (RebuildTrees(ctx,sctx,NULL)) {
  357.  
  358.                                         /* we're done now */
  359.                                         port->frp_Port.mp_Node.ln_Type=NT_MSGPORT;
  360.                                         port->frp_Port.mp_Node.ln_Name=port->frp_Name;
  361.                                         strcpy(port->frp_Name,"« MuFastRom »");
  362.                                         port->frp_Port.mp_Flags=PA_IGNORE;
  363.                                         NewList(&(port->frp_Port.mp_MsgList));
  364.  
  365.                                         port->frp_RomStart=source;
  366.                                         port->frp_Physical=pmem;
  367.                                         port->frp_Logical=mem;
  368.                                         port->frp_Size=size;
  369.                                         port->frp_NoProtect=noprotect;
  370.                                         port->frp_Protect=protect;
  371.                                         port->frp_CacheFlags=props;
  372.                                         port->frp_OldLocation=oldlocation;
  373.                                         port->frp_Base=OpenLibrary("mmu.library",0L);
  374.                                         AddPort(&(port->frp_Port));
  375.  
  376.                                         /* Do not release the memory or the port */
  377.                                         mem=NULL;
  378.                                         port=NULL;
  379.  
  380.                                         err=0;
  381.                             }
  382.                            }
  383.                           }
  384.  
  385.                           if (err) {
  386.                                   SetPropertyList(ctx,ctxl);
  387.                                   SetPropertyList(sctx,sctxl);
  388.                           }
  389.  
  390.                           ReleaseMapping(sctx,sctxl);
  391.                          }
  392.                          ReleaseMapping(ctx,ctxl);
  393.                         }
  394.  
  395.                         UnlockMMUContext(sctx);
  396.                         UnlockMMUContext(ctx);
  397.                         UnlockContextList();
  398.                         if (port) FreeMem(port,sizeof(struct FastRomPort));
  399.                  }
  400.                 }
  401.                 if (mem) FreeMem(mem,size);
  402.         }
  403.  
  404.         return err;
  405. }
  406. ///
  407. /// RemoveFastRom
  408. int RemoveFastRom(void)
  409. {
  410. struct MMUContext *ctx,*sctx;
  411. struct MinList *ctxl,*sctxl;
  412. struct FastRomPort *port;
  413. ULONG size,props;
  414. void *mem,*pmem,*source,*location;
  415. int err=ERROR_NO_FREE_STORE;
  416.  
  417.  
  418.         Forbid();                               /* Shut up PatchWork */
  419.  
  420.         /* If this is not installed, warn and return. */
  421.  
  422.         port=(struct FastRomPort *)FindPort("« MuFastRom »");
  423.  
  424.         if (port==NULL) {
  425.                 Permit();
  426.                 Printf("MuFastRom not installed.\n");
  427.                 return 5;
  428.         }
  429.         /* Remove it, to ensure nobody else tries to remove it */
  430.         RemPort(&(port->frp_Port));
  431.         Permit();
  432.  
  433.         ctx=DefaultContext();   /* get the default context */
  434.         sctx=SuperContext(ctx); /* get the supervisor context for this one */
  435.  
  436.         size=port->frp_Size;
  437.         pmem=port->frp_Physical;
  438.         mem=port->frp_Logical;
  439.         source=port->frp_RomStart;
  440.         location=port->frp_OldLocation;
  441.         props=port->frp_CacheFlags;
  442.  
  443.         /* Remove the properties right here... */
  444.  
  445.         LockContextList();
  446.         LockMMUContext(ctx);
  447.         LockMMUContext(sctx);
  448.  
  449.         if (ctxl=GetMapping(ctx)) {
  450.          if (sctxl=GetMapping(sctx)) {
  451.           if (MapToRom(ctx,(ULONG)location,(ULONG)source,(ULONG)mem,size)) {
  452.            if (MapToRom(sctx,(ULONG)location,(ULONG)source,(ULONG)mem,size)) {
  453.             if (RebuildTrees(ctx,sctx,NULL)) {
  454.  
  455.                         FreeMem(mem,size);
  456.  
  457.                         /* Close the mmu.lib so it can be flushed... */
  458.  
  459.                         if (port->frp_Base)
  460.                                 CloseLibrary(port->frp_Base);
  461.  
  462.                         FreeMem(port,sizeof(struct FastRomPort));
  463.                         err=0;
  464.             }
  465.            }
  466.           }
  467.  
  468.           if (err) {
  469.                   SetPropertyList(ctx,ctxl);
  470.                   SetPropertyList(sctx,sctxl);
  471.           }
  472.  
  473.           ReleaseMapping(sctx,sctxl);
  474.          }
  475.          ReleaseMapping(ctx,ctxl);
  476.         }
  477.  
  478.         UnlockMMUContext(sctx);
  479.         UnlockMMUContext(ctx);
  480.         UnlockContextList();
  481.  
  482.         if (err) {
  483.                 /* Better luck next time... */
  484.                 AddPort(&(port->frp_Port));
  485.                 Printf("Can't remove the FastRom node, sorry.\n");
  486.         }
  487.  
  488.         return err;
  489. }
  490. ///
  491. /// RemapToRam
  492. BOOL RemapToRam(struct MMUContext *ctx,ULONG source,ULONG pmem,ULONG mem,ULONG size,LONG protect,LONG noprotect,ULONG cacheflags)
  493. {
  494. ULONG oldprops;
  495. ULONG rommask,mirrormask;
  496.  
  497.         /* get the properties of the ROM */
  498.         oldprops=GetProperties(ctx,source,TAG_DONE);
  499.  
  500.         oldprops |= MAPP_REMAPPED;
  501.         rommask=MAPP_REMAPPED|MAPP_COPYBACK;   /* Define these bits for the ROM image */
  502.         mirrormask=0;                          /* ...and these for the RAM mirror */
  503.  
  504.         /* Protection enabled? */
  505.         if (protect) {
  506.                 /* active or passive protection? */
  507.                 if (oldprops & MAPP_WRITEPROTECTED) {
  508.                         /* here aggressive, enable protection
  509.                            and allow MuForce to repair access faults */
  510.                         rommask |= MAPP_WRITEPROTECTED|MAPP_REPAIRABLE;
  511.                         mirrormask |= MAPP_WRITEPROTECTED|MAPP_REPAIRABLE;
  512.                 } else {
  513.                         rommask |= MAPP_ROM;
  514.                         mirrormask |= MAPP_ROM;
  515.                         oldprops |= MAPP_ROM;
  516.                 }
  517.         } else if (noprotect) {
  518.                 /* disable all kinds of protection */
  519.                 oldprops &= ~(MAPP_ROM|MAPP_WRITEPROTECTED);
  520.                 rommask |= MAPP_ROM | MAPP_WRITEPROTECTED;
  521.                 mirrormask |= MAPP_ROM | MAPP_WRITEPROTECTED;
  522.         }
  523.  
  524.         /* Enter caching mode */
  525.         oldprops &= ~CACHEFLAGS;
  526.         oldprops |= cacheflags;
  527.         rommask |= CACHEFLAGS;
  528.  
  529.         if (SetProperties(ctx,oldprops,rommask,source,size,MAPTAG_DESTINATION,pmem,TAG_DONE)) {
  530.          if (SetProperties(ctx,oldprops,mirrormask,mem,size,TAG_DONE)) {
  531.            return TRUE;
  532.          }
  533.         }
  534.  
  535.         return FALSE;
  536. }
  537. ///
  538. /// MapToRom
  539. BOOL MapToRom(struct MMUContext *ctx,ULONG oldlocation,ULONG source,ULONG mem,ULONG size)
  540. {
  541. BOOL res;
  542.  
  543.  
  544.         if (oldlocation == source) {
  545.                 // No ROM remapping
  546.                 res = SetProperties(ctx,0,MAPP_REMAPPED|CACHEFLAGS,source,size,TAG_DONE);
  547.         } else {
  548.                 // ROM was remapped
  549.                 res = SetProperties(ctx,MAPP_REMAPPED,MAPP_REMAPPED|CACHEFLAGS,source,size,MAPTAG_DESTINATION,oldlocation,TAG_DONE);
  550.         }
  551.  
  552.         if (res) {
  553.          if (SetProperties(ctx,0,MAPP_ROM|MAPP_WRITEPROTECTED|MAPP_REPAIRABLE,mem,size,TAG_DONE)) {
  554.            return TRUE;
  555.          }
  556.         }
  557.  
  558.         return FALSE;
  559. }
  560. ///
  561.  
  562.  
  563.